<!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=5,IE=9" ><![endif]-->
<!DOCTYPE html>
<html>
<head>
	<script type="text/javascript">
		mxBasePath = '../../../javascript/src';
	</script>
	<script type="text/javascript" src="../../../javascript/src/js/mxClient.js"></script>
	<script type="text/javascript">
		function getSvg(graph, background, scale, border)
		{
			scale = (scale != null) ? scale : 1;
			border = (border != null) ? border : 1;
	
			var imgExport = new mxImageExport();
			var bounds = graph.getGraphBounds();
			var vs = graph.view.scale;
	
			// Prepares SVG document that holds the output
			var svgDoc = mxUtils.createXmlDocument();
			var root = (svgDoc.createElementNS != null) ?
		    		svgDoc.createElementNS(mxConstants.NS_SVG, 'svg') : svgDoc.createElement('svg');
		    
			if (background != null)
			{
				if (root.style != null)
				{
					root.style.backgroundColor = background;
				}
				else
				{
					root.setAttribute('style', 'background-color:' + background);
				}
			}
		    
			if (svgDoc.createElementNS == null)
			{
		    	root.setAttribute('xmlns', mxConstants.NS_SVG);
			}
			else
			{
				// KNOWN: Ignored in IE9-11, adds namespace for each image element instead. No workaround.
				root.setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:xlink', mxConstants.NS_XLINK);
			}
			
			root.setAttribute('width', (Math.ceil(bounds.width * scale / vs) + 2 * border) + 'px');
			root.setAttribute('height', (Math.ceil(bounds.height * scale / vs) + 2 * border) + 'px');
			root.setAttribute('version', '1.1');
			
		    // Adds group for anti-aliasing via transform
			var group = (svgDoc.createElementNS != null) ?
					svgDoc.createElementNS(mxConstants.NS_SVG, 'g') : svgDoc.createElement('g');
			group.setAttribute('transform', 'translate(0.5,0.5)');
			root.appendChild(group);
			svgDoc.appendChild(root);
	
		    // Renders graph. Offset will be multiplied with state's scale when painting state.
			var svgCanvas = new mxSvgCanvas2D(group);
			svgCanvas.translate(Math.floor((border / scale - bounds.x) / vs), Math.floor((border / scale - bounds.y) / vs));
			svgCanvas.scale(scale / vs);
			imgExport.drawState(graph.getView().getState(graph.model.root), svgCanvas);
	
			return root;
		};

		// Program starts here. Creates a sample graph in the
		// DOM node with the specified ID. This function is invoked
		// from the onLoad event handler of the document (see below).
		function main(container)
		{
			// Checks if the browser is supported
			if (!mxClient.isBrowserSupported())
			{
				// Displays an error message if the browser is not supported.
				mxUtils.error('Browser is not supported!', 200, false);
			}
			else
			{
				// Disables the built-in context menu
				mxEvent.disableContextMenu(container);
				
				// Creates the graph inside the given container
				var graph = new mxGraph(container);
				
				// FIXME: With HTML we get "tainted canvases may not be exported" error
				// graph.setHtmlLabels(true);

				// Enables rubberband selection
				new mxRubberband(graph);
				
				// Gets the default parent for inserting new cells. This
				// is normally the first child of the root (ie. layer 0).
				var parent = graph.getDefaultParent();
								
				// Adds cells to the model in a single step
				graph.getModel().beginUpdate();
				try
				{
					var v1 = graph.insertVertex(parent, null, 'No HTML', 20, 20, 80, 40);
					var v2 = graph.insertVertex(parent, null, 'No CORS', 200, 150, 80, 30);
					var e1 = graph.insertEdge(parent, null, '', v1, v2);
				}
				finally
				{
					// Updates the display
					graph.getModel().endUpdate();
				}
				
				document.body.appendChild(mxUtils.button('Export PNG', function()
				{
					var data = mxUtils.getXml(getSvg(graph));
					var bounds = graph.getGraphBounds();
					
					var canvas = document.createElement('canvas');
					canvas.setAttribute('width', bounds.width + 4);
					canvas.setAttribute('height', bounds.height + 4);
					canvas.style.border = '1px solid black';
					var ctx = canvas.getContext('2d');

					var img = new Image();

					img.onload = function()
					{
					    ctx.drawImage(img, 0, 0);
					    URL.revokeObjectURL(img.src);
					    
						var data = canvas.toDataURL().replace(/data:image\/png;base64,/,'');
						var blob = base64toBlob(data, 'image/png');
						
						var a = document.createElement('a');
						a.href = URL.createObjectURL(blob);
						a.download = 'export.png';
						a.click();
						
						URL.revokeObjectURL(a.href);
					};
					
		          	var svg = mxUtils.getXml(getSvg(graph));
					var b = new Blob([svg], {type: 'image/svg+xml;charset=utf-8'});
					img.src = URL.createObjectURL(b);
				}));
			}
		};
		
		// TODO: Built-in solution for converting base64 to binary array?
		function base64toBlob(base64Data, contentType)
		{
		    contentType = contentType || '';
		    var sliceSize = 1024;
		    var byteCharacters = atob(base64Data);
		    var bytesLength = byteCharacters.length;
		    var slicesCount = Math.ceil(bytesLength / sliceSize);
		    var byteArrays = new Array(slicesCount);

		    for (var sliceIndex = 0; sliceIndex < slicesCount; ++sliceIndex)
		    {
		        var begin = sliceIndex * sliceSize;
		        var end = Math.min(begin + sliceSize, bytesLength);

		        var bytes = new Array(end - begin);
		        
		        for (var offset = begin, i = 0 ; offset < end; ++i, ++offset)
		        {
		            bytes[i] = byteCharacters[offset].charCodeAt(0);
		        }
		        
		        byteArrays[sliceIndex] = new Uint8Array(bytes);
		    }
		    
		    return new Blob(byteArrays, {type: contentType});
		};
	</script>
</head>

<!-- Page passes the container for the graph to the program -->
<body onload="main(document.getElementById('graphContainer'))">

	<!-- Creates a container for the graph with a grid wallpaper -->
	<div id="graphContainer"
		style="position:relative;overflow:hidden;width:321px;height:241px;border: 1px solid gray;cursor:default;">
	</div>
</body>
</html>
